iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 24
0

Everything is Object

今天來談談prototype一些注意的細節,我們知道Javascript裡面所有的變數都是一個物件不然就是Primtive,也就是說除了primitive - number, string, boolean, ect 以外,全都是物件 - function、array、basic objects. 所有的物件以及primitive都有prototype。

但唯一有一個例外,base object,也就是object的最底層。

Everything has a prototype

讓我們用一下範例來看一下prototype吧,我們用basic object、function、array為例子。

var a = {};
function b() {};
var c = [];

Object a

https://ithelp.ithome.com.tw/upload/images/20180112/20107670VPbEdCbxuX.png

我們看到了物件a的proto仍然是一個物件,而其中擁有許多property以及method,其中我們可以看到熟悉的toString()。

function b

https://ithelp.ithome.com.tw/upload/images/20180112/20107670uPWtprPibr.png

https://ithelp.ithome.com.tw/upload/images/20180112/20107670BuBJpxiulL.png

function b的proto則是一個function object,而其中包含的許多method,包含我們先前才介紹的call()、apply()、bind(),這也就是為什麼每個function都能使用這三個method的原因,就是擁有這個function prototype。

array c

https://ithelp.ithome.com.tw/upload/images/20180112/20107670mzGfNCeZRR.png

array的proto我們看到了仍然是一個object,而這個object包含了常見的array method,包括了 pop()、push() ... ,所有的array proto都會指到這一個object,也就是為何每個array都可以用到常見的method。

Tricky

透過三個範例知道了為什麼平常可以用一些好用的method了嗎,這就是prototype的功力阿,

那如果這些proto的proto又是什麼呢。

https://ithelp.ithome.com.tw/upload/images/20180112/20107670jYmhhIlphc.png

這就是最底層的object了,每個object都共享的base object。

reflection & extend

接下來我們深入探討一下object的兩個觀念,有助於我們理解prototype的運作

Reflection

Reflection的定義為,object可以查看自己,列出並更改自己的properties & methods。所以Javascript Object能夠觀察自己的properties & methods。

透過這樣的一個特性我們可以實行一個好用的pattern - extend。
那我們先來看一下 Reflection的範例。

var person = {
	firstName: 'Default',
	lastName: 'Default',
	getFullName: function() {
		return this.firstName + ' ' + this.lastName;
	}

}

var john = {
	firstName: 'Ben',
	lastName: 'Lee'
}

//千萬不要亂用__proto__,此為demo。
john.__proto__ = person;

for ( var prop in john) {
	console.log(prop + ': ' + john[prop]);
}

得到的結果為

https://ithelp.ithome.com.tw/upload/images/20180112/20107670uDsxjdT4Bk.png

有沒有發現哪裡怪怪的,proto的method也被列出來了,這樣未免也太混淆了,所以我們可以透過 hasOwnProperty()method,只查看自己物件的property就好。

for ( var prop in john) {
	if(john.hasOwnProperty(prop)) {
		console.log(prop + ': ' + john[prop]);
	}
}

因此我們可以reflect john object,查看它的properties & method。

Extend

透過上述我們知道object可以查看自己,並運用此特性做extend,也就是雖然可以share object內的property & methods,但有時候object會想要新增一些功能而不要是prototype型態,這時候我們就能利用extends來達到。

var person = {
	firstName: 'Default',
	lastName: 'Default',
	getFullName: function() {
		return this.firstName + ' ' + this.lastName;
	}

}

var john = {
	firstName: 'Ben',
	lastName: 'Lee'
}

//千萬不要亂用__proto__,此為demo。
john.__proto__ = person;

for ( var prop in john) {
	console.log(prop + ': ' + john[prop]);
}

var jane = {
	addess: '111 Main St.',
	getFormalFullName: function() {
		return this.lastName + ', ' + this.firstName;
	}
}

$.extend(true, john, jane);
console.log(john);

https://ithelp.ithome.com.tw/upload/images/20180112/20107670PUxZmy4jA5.png

上面的範例中,我們透過extend將兩個物件結合起來,不同於prototype,extends只屬於特定object,將原本的物件做擴增的動作,而這也常被應用於library,也就是我們可以透過extend的作法,寫出自己的library,我們可以結合objects,而不需要一直透過prototype chain。

參考來源

  1. Udemy Course - JavaScript: Understanding the Weird Parts

上一篇
Day23_先別管鐵人賽拉,你們看過新的勞基法了嗎。
下一篇
Day25_let 薑母鴨 = New hotspot('薑母鴨')
系列文
那些年,我們一起錯過的Javascript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言